package com.system.boot.rbac.service.impl;

import cn.hutool.core.bean.BeanException;
import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.system.api.SuperInterface;
import com.system.api.company.entity.po.SysCompany;
import com.system.api.rbac.entity.bo.RoleComPanyBo;
import com.system.api.rbac.entity.po.SysRole;
import com.system.api.rbac.entity.po.SysRolePermissionRelation;
import com.system.api.rbac.entity.vo.RoleListVo;
import com.system.boot.company.mapper.CompanyMapper;
import com.system.boot.rbac.converter.RoleConverter;
import com.system.boot.rbac.mapper.RoleMapper;
import com.system.boot.rbac.mapper.RoleMenuRelationMapper;
import com.system.boot.rbac.mapper.RolePermissionRelationMapper;
import com.system.boot.rbac.service.RoleService;
import com.system.common.constant.SystemConstant;
import com.system.common.enums.SuperEnum;
import lombok.RequiredArgsConstructor;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.yang.common.core.enums.BusinessStatusEnum;
import org.yang.common.core.exception.BaseException;
import org.yang.common.i18n.constant.I18nMessageConstant;
import org.yang.common.utils.jwt.JwtTokenAnalysisUtli;
import org.yang.database.orm.entity.BaseModel;
import org.yang.database.orm.entity.BaseQuery;
import org.yang.database.orm.entity.Options;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author: lslands
 * @description:
 * @version：v1.0
 * @date: 2024/6/2 18:43
 */
@Service
@RequiredArgsConstructor
public class RoleServiceImpl extends ServiceImpl<RoleMapper, SysRole> implements RoleService, SuperInterface<SysRole> {

  private final RoleConverter roleConverter;

  @Override
  public void isExists(Long companyId, String name, String code) throws BaseException {
    boolean existsByName = baseMapper.getExistsByName(companyId, name);
    if (existsByName) {
      throw new BaseException(BaseException.REPEAT, name);
    }
    boolean existsByCode = baseMapper.getExistsByCode(companyId, code);
    if (existsByCode) {
      throw new BaseException(BaseException.REPEAT, code);
    }
  }


  @Override
  public int handInsert(SysRole record) throws BaseException {
    if (null != record.getCode()) {
      this.isExists(record.getCompanyId(), record.getName(), record.getCode());
    }
    return baseMapper.insert(record);
  }

  @Override
  public int handUpdateById(SysRole record) throws BaseException {
    SysRole oldResult =
        Optional.ofNullable(baseMapper.selectById(record.getId()))
            .orElseThrow(() -> new BaseException(BaseException.NULL));
    if (!Objects.equals(record, oldResult)) {
      if (!record.getName().equals(oldResult.getName())
          || !record.getCode().equals(oldResult.getCode())) {
        this.isExists(record.getCompanyId(), record.getName(), record.getCode());
      }
      return baseMapper.updateById(record);
    }
    return 1;
  }

  @Override
  public int handEnabledById(Long id, Integer enabled, Integer revision) throws BaseException {
    SysRole oldResult =
        Optional.ofNullable(baseMapper.selectById(id))
            .orElseThrow(() -> new BaseException(BaseException.NULL));
    if (null == enabled) {
      throw new BaseException(I18nMessageConstant.VALIDATION_STATUS_EMPTY);
    }
    if (enabled.equals(oldResult.getEnabled())) {
      return 1;
    }
    return baseMapper.updateById(new SysRole(id, enabled, revision));
  }

  @Override
  public Page<SysRole> getPage(BaseQuery query, SysRole record) {
    List<? extends Number> companyList = List.of(record.getCompanyId(), 0);
    Page<SysRole> page = new Page<>(query.getCurrent(), query.getSize());
    LambdaQueryWrapper<SysRole> wrapper = new LambdaQueryWrapper<SysRole>()
            .select(BaseModel::getId,SysRole::getName,SysRole::getCode,SysRole::getCompanyId,
                    SysRole::getDescription,BaseModel::getEnabled)
            .like(StringUtils.isNotBlank(record.getName()), SysRole::getName, record.getName())
            .eq(record.getEnabled()!=null,SysRole::getEnabled,record.getEnabled())
            .in(SysRole::getCompanyId,companyList)
            .orderByDesc(BaseModel::getId);
    return baseMapper.selectPage(page, wrapper);
  }

  @Override
  public List<RoleListVo> listTree(Long companyId, List<String> roleCodes) throws BaseException {
    LambdaQueryWrapper<SysRole> wrapper = new LambdaQueryWrapper<SysRole>().select(BaseModel::getId, SysRole::getName)
            .eq(BaseModel::getEnabled, BusinessStatusEnum.OPEN.getValue())
            .eq(SysRole::getCompanyId, companyId).or().eq(SysRole::getCompanyId,SuperEnum.COMMON.getValue());
    //判断角色是否为指定超级角色
    if(new HashSet<>(roleCodes).containsAll(SystemConstant.SUPER_ROLE)){
      //判断是否查询用户是否属于超级企业
      if(Objects.equals(companyId, SuperEnum.COMPANY.getValue())){
        List<RoleListVo> voList = new ArrayList<>();
        //查询结果->先分组，再遍历
        Optional.ofNullable(baseMapper.selectRoleCompany())
                .orElseThrow(()->new BaseException(BaseException.NULL))
                .stream().collect(Collectors.groupingBy(RoleComPanyBo::getCompanyId))
                .forEach((key, values) -> {
                  List<String> stringList = values.stream().map(RoleComPanyBo::getCompanyName).toList();
                  RoleListVo advertTreeVo = new RoleListVo(key,stringList.get(0),
                          values.stream().map(x -> new RoleListVo(x.getId(), x.getName(), new ArrayList<>())).toList());
                  voList.add(advertTreeVo);
                });
        return voList;
      }
    }else{
      wrapper.in(SysRole::getCode,roleCodes);
    }
    List<SysRole> roleList = Optional.ofNullable(baseMapper.selectList(wrapper))
            .orElse(new ArrayList<>());
    return roleConverter.listPoEntity(roleList);
  }

  @Override
  public List<Options<Integer>> listOptions(Long companyId, List<String> roleCodes) throws BaseException {
    List<SysRole> roleList;
    List<? extends Number> companyList = List.of(companyId, 0);
    LambdaQueryWrapper<SysRole> wrapper = new LambdaQueryWrapper<SysRole>()
            .select(BaseModel::getId, SysRole::getName)
            .eq(BaseModel::getEnabled, 1).in(SysRole::getCompanyId, companyList);
    if(new HashSet<>(roleCodes).containsAll(SystemConstant.SUPER_ROLE)){
      roleList = baseMapper.selectList(wrapper);
    }else{
      wrapper.in(SysRole::getCode,roleCodes);
       roleList = baseMapper.selectList(wrapper);
    }
    return Optional.of(roleList.stream().map(x -> new Options<Integer>(x.getId().intValue(), x.getName())).toList())
            .orElse(new ArrayList<Options<Integer>>());
  }


  @Override
  public int deleteOne(Long id) throws BaseException {
    if( Objects.isNull(id)){
      throw new BaseException("id cannot be null");
    }
    return baseMapper.deleteById(id);
  }

  @Override
  public int deleteBatch(Boolean delete, List<Long> ids) throws BaseException {
    if(ids.isEmpty()){
      return 0;
    }
    return delete?baseMapper.deleteBatch(ids):baseMapper.deleteBatchIds(ids);
  }

}
